package handlers

import (
	"fmt"

	"strconv"
	"strings"
	"sysu-giep/internal/api/middleware"
	"sysu-giep/internal/database/models"
	"sysu-giep/internal/service"
	"sysu-giep/pkg/logger"
	"sysu-giep/pkg/response"
	"time"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// 请求结构体定义
type CreateProjectRequest struct {
	Title        string       `json:"title" binding:"required"`
	Description  string       `json:"description" binding:"required"`
	Requirements string       `json:"requirements"`
	Budget       float64      `json:"budget"`
	Deadline     FlexibleTime `json:"deadline"`
	Category     string       `json:"category"`
	Tags         []string     `json:"tags"`
	ContactInfo  string       `json:"contact_info"`
	IsPublic     bool         `json:"is_public"`
}

type UpdateProjectRequest struct {
	Title        string       `json:"title"`
	Description  string       `json:"description"`
	Requirements string       `json:"requirements"`
	Budget       float64      `json:"budget"`
	Deadline     FlexibleTime `json:"deadline"`
	Category     string       `json:"category"`
	Tags         []string     `json:"tags"`

	ContactInfo string `json:"contact_info"`
	IsPublic    bool   `json:"is_public"`
}

type ApplyProjectRequest struct {
	CoverLetter string `json:"cover_letter" binding:"required"`
	Resume      string `json:"resume"`
	Portfolio   string `json:"portfolio"`
}

var projectService *service.ProjectService

// InitProjectHandlers 初始化课题处理器
func InitProjectHandlers(ps *service.ProjectService) {
	projectService = ps
}

// GetProjects 获取课题列表
// @Summary 获取课题列表
// @Description 获取课题列表，支持分页和筛选
// @Tags 课题
// @Accept json
// @Produce json
// @Param page query int false "页码" default(1)
// @Param size query int false "每页数量" default(10)
// @Param keyword query string false "搜索关键词"
// @Param status query string false "课题状态" Enums(open, closed, in_progress, completed)
// @Param category query string false "课题分类"
// @Success 200 {object} response.PageResponse{data=[]models.Project}
// @Router /projects [get]
func GetProjects(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
	keyword := c.Query("keyword")
	category := c.Query("category")
	status := c.Query("status")
	budgetMin, _ := strconv.ParseFloat(c.Query("budget_min"), 64)
	budgetMax, _ := strconv.ParseFloat(c.Query("budget_max"), 64)
	isPublic := c.Query("is_public")

	// 参数验证
	if page < 1 {
		page = 1
	}
	if size < 1 || size > 100 {
		size = 10
	}

	// 验证状态值
	if status != "" {
		validStatuses := []string{"open", "closed", "in_progress", "completed"}
		isValidStatus := false
		for _, validStatus := range validStatuses {
			if status == validStatus {
				isValidStatus = true
				break
			}
		}
		if !isValidStatus {
			response.BadRequest(c, "无效的课题状态")
			return
		}
	}

	// 使用ProjectService获取课题列表
	projects, total, err := projectService.GetProjects(page, size, keyword, category, status, 0, "", "", budgetMin, budgetMax, isPublic)
	if err != nil {
		logger.ErrorLog("获取课题列表失败", zap.Error(err))
		response.InternalServerError(c, "获取课题列表失败")
		return
	}

	response.PageSuccess(c, projects, total, page, size)
}

// GetProjectByID 根据ID获取课题详情
// @Summary 获取课题详情
// @Description 根据课题ID获取课题详细信息
// @Tags 课题
// @Accept json
// @Produce json
// @Param id path int true "课题ID"
// @Success 200 {object} response.Response{data=models.Project}
// @Failure 404 {object} response.Response
// @Router /projects/{id} [get]
func GetProjectByID(c *gin.Context) {
	idStr := c.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的课题ID")
		return
	}

	// 使用ProjectService获取课题详情
	project, err := projectService.GetProjectByID(id)
	if err != nil {
		logger.ErrorLog("获取课题详情失败", zap.Uint64("project_id", id), zap.Error(err))
		response.NotFound(c, "课题不存在")
		return
	}

	response.Success(c, project)
}

// CreateProject 创建课题
// @Summary 创建课题
// @Description 创建新课题（仅企业用户）
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body CreateProjectRequest true "课题信息"
// @Success 200 {object} response.Response{data=models.Project}
// @Failure 400 {object} response.Response
// @Router /projects [post]
func CreateProject(c *gin.Context) {
	userID := middleware.GetCurrentUserID(c)

	var req CreateProjectRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	// 参数验证
	if req.Title == "" {
		response.BadRequest(c, "课题标题不能为空")
		return
	}
	title := req.Title

	if req.Description == "" {
		response.BadRequest(c, "课题描述不能为空")
		return
	}
	description := req.Description

	if req.Requirements == "" {
		response.BadRequest(c, "课题要求不能为空")
		return
	}
	requirements := req.Requirements

	if req.Budget <= 0 {
		response.BadRequest(c, "预算必须大于0")
		return
	}
	budget := req.Budget

	if req.Deadline.IsZero() {
		response.BadRequest(c, "截止日期不能为空")
		return
	}
	deadline := req.Deadline.Time

	if req.Category == "" {
		response.BadRequest(c, "课题分类不能为空")
		return
	}
	category := req.Category

	if len(req.Tags) == 0 {
		response.BadRequest(c, "课题标签不能为空")
		return
	}
	tags := req.Tags

	// 使用ProjectService创建课题
	project := &models.Project{
		CreatorID:    userID,
		Title:        title,
		Description:  description,
		Requirements: requirements,
		Budget:       budget,
		Deadline:     deadline,
		Category:     category,
		Tags:         strings.Join(tags, ","),
		Status:       "open", // 默认状态为开放
		ContactInfo:  req.ContactInfo,
		IsPublic:     req.IsPublic,
		ViewCount:    0,
		ApplyCount:   0,
	}

	err := projectService.CreateProject(project)
	if err != nil {
		logger.ErrorLog("创建课题失败", zap.Error(err))
		response.InternalServerError(c, "创建课题失败")
		return
	}

	response.SuccessWithMessage(c, "课题创建成功", project)
}

// UpdateProject 更新课题
// @Summary 更新课题
// @Description 更新课题信息（仅课题创建者）
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "课题ID"
// @Param request body UpdateProjectRequest true "课题信息"
// @Success 200 {object} response.Response{data=models.Project}
// @Failure 400 {object} response.Response
// @Router /projects/{id} [put]
func UpdateProject(c *gin.Context) {
	userID := middleware.GetCurrentUserID(c)
	idStr := c.Param("id")

	projectID, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的课题ID")
		return
	}

	var req UpdateProjectRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	// 验证用户是否有权限更新该课题
	project, err := projectService.GetProjectByID(projectID)
	if err != nil {
		logger.ErrorLog("获取课题失败", zap.Uint64("project_id", projectID), zap.Error(err))
		response.NotFound(c, "课题不存在")
		return
	}
	//只有创建者可以更新
	if project.CreatorID != userID {
		response.Forbidden(c, "无权限更新该课题")
		return
	}

	// 构建更新字段
	updates := make(map[string]interface{})
	if req.Title != "" {
		updates["title"] = req.Title
	}
	if req.Description != "" {
		updates["description"] = req.Description
	}
	if req.Requirements != "" {
		updates["requirements"] = req.Requirements
	}
	if req.Budget > 0 {
		updates["budget"] = req.Budget
	}
	if !req.Deadline.IsZero() {
		updates["deadline"] = req.Deadline.Time
	}
	if req.Category != "" {
		updates["category"] = req.Category
	}
	if len(req.Tags) > 0 {
		updates["tags"] = strings.Join(req.Tags, ",")
	}

	if req.ContactInfo != "" {
		updates["contact_info"] = req.ContactInfo
	}
	// IsPublic是bool类型，需要特殊处理
	updates["is_public"] = req.IsPublic

	if len(updates) == 0 {
		response.BadRequest(c, "没有提供有效的更新字段")
		return
	}

	// 使用ProjectService更新课题
	err = projectService.UpdateProject(projectID, updates)
	if err != nil {
		logger.ErrorLog("更新课题失败", zap.Error(err))
		response.InternalServerError(c, "更新课题失败")
		return
	}

	// 获取更新后的课题信息
	updatedProject, err := projectService.GetProjectByID(projectID)
	if err != nil {
		logger.ErrorLog("获取更新后的课题失败", zap.Error(err))
		response.InternalServerError(c, "获取更新后的课题失败")
		return
	}

	response.SuccessWithMessage(c, "课题更新成功", updatedProject)
}

// DeleteProject 删除课题
// @Summary 删除课题
// @Description 删除课题（仅课题创建者）
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "课题ID"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /projects/{id} [delete]
func DeleteProject(c *gin.Context) {
	userID := middleware.GetCurrentUserID(c)
	idStr := c.Param("id")

	projectID, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的课题ID")
		return
	}

	// 验证用户是否有权限删除该课题
	project, err := projectService.GetProjectByID(projectID)
	if err != nil {
		logger.ErrorLog("获取课题失败", zap.Error(err))
		response.NotFound(c, "课题不存在")
		return
	}

	if project.CreatorID != userID {
		response.Forbidden(c, "无权限删除该课题")
		return
	}

	// 检查课题状态，已完成的课题不能删除
	if project.Status == "completed" {
		response.BadRequest(c, "已完成的课题不能删除")
		return
	}

	// 检查是否有进行中的申请
	hasActiveApplications, err := projectService.HasActiveApplications(projectID)
	if err != nil {
		logger.ErrorLog("检查课题申请状态失败", zap.Error(err))
		response.InternalServerError(c, "检查课题申请状态失败")
		return
	}

	if hasActiveApplications {
		response.BadRequest(c, "课题有进行中的申请，不能删除")
		return
	}

	// 使用ProjectService删除课题
	err = projectService.DeleteProject(projectID)
	if err != nil {
		logger.ErrorLog("删除课题失败", zap.Error(err))
		response.InternalServerError(c, "删除课题失败")
		return
	}

	response.SuccessWithMessage(c, "课题删除成功", gin.H{
		"deleted_project_id": projectID,
		"deleted_at":         time.Now().Format("2006-01-02T15:04:05Z"),
	})
}

// ApplyProject 申请课题
// @Summary 申请课题
// @Description 申请课题（导师或学生）
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "课题ID"
// @Param request body ApplyProjectRequest true "申请信息"
// @Success 200 {object} response.Response{data=models.Application}
// @Failure 400 {object} response.Response
// @Router /projects/{id}/applications [post]
func ApplyProject(c *gin.Context) {
	userID := middleware.GetCurrentUserID(c)
	idStr := c.Param("id")

	projectID, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的课题ID")
		return
	}

	var req ApplyProjectRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "请求参数错误: "+err.Error())
		return
	}

	// 参数验证
	if req.CoverLetter == "" {
		response.BadRequest(c, "申请信不能为空")
		return
	}

	// 检查课题是否存在且状态为开放
	project, err := projectService.GetProjectByID(projectID)
	if err != nil {
		logger.ErrorLog("获取课题失败", zap.Error(err))
		response.NotFound(c, "课题不存在")
		return
	}

	if project.Status != "open" {
		response.BadRequest(c, "课题当前不接受申请")
		return
	}

	// 检查用户是否已经申请过该课题
	alreadyApplied, err := projectService.HasUserApplied(projectID, uint64(userID))
	if err != nil {
		logger.ErrorLog("检查用户申请状态失败", zap.Error(err))
		response.InternalServerError(c, "检查用户申请状态失败")
		return
	}

	if alreadyApplied {
		response.BadRequest(c, "您已经申请过该课题")
		return
	}

	// 创建申请记录
	application := &models.Application{
		ProjectID:   uint(projectID),
		ApplicantID: userID,
		Status:      "pending",
		CoverLetter: req.CoverLetter,
		Resume:      req.Resume,
		ApplyDate:   time.Now(),
	}

	err = projectService.ApplyProject(application)
	if err != nil {
		logger.ErrorLog("创建申请失败", zap.Error(err))
		response.InternalServerError(c, "申请提交失败")
		return
	}

	response.SuccessWithMessage(c, "申请提交成功", application)
}

// GetMyProjects 获取我的课题
// @Summary 获取我的课题
// @Description 获取当前用户创建的课题列表
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码" default(1)
// @Param size query int false "每页数量" default(10)
// @Success 200 {object} response.PageResponse{data=[]models.Project}
// @Router /projects/my [get]
func GetMyProjects(c *gin.Context) {
	userID := middleware.GetCurrentUserID(c)
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))

	// 参数验证
	if page < 1 {
		page = 1
	}
	if size < 1 || size > 100 {
		size = 10
	}

	// 使用ProjectService获取我的课题列表
	projects, total, err := projectService.GetMyProjects(uint64(userID), page, size, "")
	if err != nil {
		logger.ErrorLog("获取我的课题失败", zap.Error(err))
		response.InternalServerError(c, "获取我的课题失败")
		return
	}

	response.PageSuccess(c, projects, total, page, size)
}

// SearchProjects 搜索课题
// @Summary 搜索课题
// @Description 根据关键词搜索课题
// @Tags 课题
// @Accept json
// @Produce json
// @Param q query string true "搜索关键词"
// @Param page query int false "页码" default(1)
// @Param size query int false "每页数量" default(10)
// @Param category query string false "课题分类"
// @Param budget_min query number false "最小预算"
// @Param budget_max query number false "最大预算"
// @Success 200 {object} response.PageResponse{data=[]models.Project}
// @Router /projects/search [get]
func SearchProjects(c *gin.Context) {
	query := c.Query("q")
	if query == "" {
		response.BadRequest(c, "搜索关键词不能为空")
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))
	category := c.Query("category")
	budgetMin, _ := strconv.ParseFloat(c.Query("budget_min"), 64)
	budgetMax, _ := strconv.ParseFloat(c.Query("budget_max"), 64)

	// 参数验证
	if page < 1 {
		page = 1
	}
	if size < 1 || size > 100 {
		size = 10
	}

	// 使用ProjectService的Elasticsearch搜索功能
	projects, total, err := projectService.SearchProjects(query, page, size, category, budgetMin, budgetMax, 0, 0)
	if err != nil {
		logger.ErrorLog("搜索课题失败", zap.Error(err))
		response.InternalServerError(c, "搜索课题失败")
		return
	}

	response.PageSuccess(c, projects, total, page, size)
}

// GetProjectCategories 获取课题分类
// @Summary 获取课题分类
// @Description 获取所有可用的课题分类
// @Tags 课题
// @Accept json
// @Produce json
// @Success 200 {object} response.Response{data=[]map[string]interface{}}
// @Router /projects/categories [get]
func GetProjectCategories(c *gin.Context) {
	// 使用ProjectService获取分类
	categories, err := projectService.GetProjectCategories()
	if err != nil {
		logger.ErrorLog("获取课题分类失败", zap.Error(err))
		response.InternalServerError(c, "获取课题分类失败")
		return
	}

	response.Success(c, categories)
}

// FavoriteProject 收藏课题
// @Summary 收藏课题
// @Description 收藏指定课题
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "课题ID"
// @Success 200 {object} response.Response
// @Router /projects/{id}/favorite [post]
func FavoriteProject(c *gin.Context) {
	userID := middleware.GetCurrentUserID(c)
	idStr := c.Param("id")

	projectID, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的课题ID")
		return
	}

	// 检查课题是否存在
	_, err = projectService.GetProjectByID(projectID)
	if err != nil {
		logger.ErrorLog("获取课题失败", zap.Uint64("project_id", projectID), zap.Error(err))
		response.NotFound(c, "课题不存在")
		return
	}

	// 检查用户是否已经收藏过该课题
	alreadyFavorited, err := projectService.HasUserFavorited(projectID, uint64(userID))
	if err != nil {
		logger.ErrorLog("检查用户收藏状态失败", zap.Uint64("project_id", projectID), zap.Error(err))
		response.InternalServerError(c, "检查用户收藏状态失败")
		return
	}

	if alreadyFavorited {
		response.BadRequest(c, "您已经收藏过该课题")
		return
	}

	// 使用ProjectService添加收藏记录
	err = projectService.FavoriteProject(uint64(userID), projectID)
	if err != nil {
		logger.ErrorLog("收藏课题失败", zap.Error(err))
		response.InternalServerError(c, "收藏课题失败")
		return
	}

	response.SuccessWithMessage(c, "课题收藏成功", gin.H{
		"project_id":   projectID,
		"user_id":      userID,
		"favorited_at": time.Now().Format("2006-01-02T15:04:05Z"),
	})
}

// UnfavoriteProject 取消收藏课题
// @Summary 取消收藏课题
// @Description 取消收藏指定课题
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "课题ID"
// @Success 200 {object} response.Response
// @Router /projects/{id}/favorite [delete]
func UnfavoriteProject(c *gin.Context) {
	userID := middleware.GetCurrentUserID(c)
	idStr := c.Param("id")

	projectID, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的课题ID")
		return
	}

	// 检查课题是否存在
	_, err = projectService.GetProjectByID(projectID)
	if err != nil {
		logger.ErrorLog("获取课题失败", zap.Uint64("project_id", projectID), zap.Error(err))
		response.NotFound(c, "课题不存在")
		return
	}

	// 检查用户是否已经收藏过该课题
	alreadyFavorited, err := projectService.HasUserFavorited(projectID, uint64(userID))
	if err != nil {
		logger.ErrorLog("检查用户收藏状态失败", zap.Uint64("project_id", projectID), zap.Error(err))
		response.InternalServerError(c, "检查用户收藏状态失败")
		return
	}

	if !alreadyFavorited {
		response.BadRequest(c, "您还没有收藏过该课题")
		return
	}

	// 使用ProjectService删除收藏记录
	err = projectService.UnfavoriteProject(uint64(userID), projectID)
	if err != nil {
		logger.ErrorLog("取消收藏课题失败", zap.Uint64("project_id", projectID), zap.Error(err))
		response.InternalServerError(c, "取消收藏失败")
		return
	}

	response.SuccessWithMessage(c, "取消收藏成功", gin.H{
		"project_id":     projectID,
		"user_id":        userID,
		"unfavorited_at": time.Now().Format("2006-01-02T15:04:05Z"),
	})
}

// GetFavoriteProjects 获取收藏的课题
// @Summary 获取收藏的课题
// @Description 获取当前用户收藏的课题列表
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param page query int false "页码" default(1)
// @Param size query int false "每页数量" default(10)
// @Success 200 {object} response.PageResponse{data=[]models.Project}
// @Router /projects/favorites [get]
func GetFavoriteProjects(c *gin.Context) {
	userID := middleware.GetCurrentUserID(c)
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	size, _ := strconv.Atoi(c.DefaultQuery("size", "10"))

	// 参数验证
	if page < 1 {
		page = 1
	}
	if size < 1 || size > 100 {
		size = 10
	}

	// 使用ProjectService获取用户收藏的课题
	projects, total, err := projectService.GetFavoriteProjects(uint64(userID), page, size)
	if err != nil {
		logger.ErrorLog("获取收藏课题失败", zap.Uint64("user_id", uint64(userID)), zap.Error(err))
		response.InternalServerError(c, "获取收藏课题失败")
		return
	}

	response.PageSuccess(c, projects, total, page, size)
}

// ShareProject 分享课题
// @Summary 分享课题
// @Description 生成课题分享链接，所有人都可以分享
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "课题ID"
// @Success 200 {object} response.Response{data=map[string]interface{}}
// @Router /projects/{id}/share [post]
func ShareProject(c *gin.Context) {
	userID := middleware.GetCurrentUserID(c)
	idStr := c.Param("id")

	projectID, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的课题ID")
		return
	}

	// 检查课题是否存在
	project, err := projectService.GetProjectByID(projectID)
	if err != nil {
		logger.ErrorLog("获取课题失败", zap.Uint64("project_id", projectID), zap.Error(err))
		response.NotFound(c, "课题不存在")
		return
	}

	// 生成分享链接（从配置获取基础URL）
	baseURL := "https://example.com" // 这里应该从配置中获取
	shareURL := fmt.Sprintf("%s/projects/%d", baseURL, projectID)

	// 生成二维码URL
	qrCodeURL := fmt.Sprintf("%s/qr/projects/%d", baseURL, projectID)

	// 构建响应数据
	shareInfo := map[string]interface{}{
		"share_url":   shareURL,
		"qr_code_url": qrCodeURL,
		"project_info": map[string]interface{}{
			"id":    project.ID,
			"title": project.Title,
		},
		"shared_at": time.Now().Format("2006-01-02T15:04:05Z"),
		"shared_by": userID,
	}

	response.SuccessWithMessage(c, "课题分享成功", shareInfo)
}

// GetRecommendedProjects 获取推荐的匹配课题列表
// @Summary 获取推荐的匹配课题列表
// @Description 根据学生信息匹配适合的课题，按匹配分数排序返回
// @Tags 课题
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param student_id query int true "学生ID"
// @Param top_k query int false "返回Top K个课题" default(10)
// @Success 200 {object} response.Response{data=[]RecommendedProject}
// @Failure 400 {object} response.Response
// @Router /projects/recommendations [get]
func GetRecommendedProjects(c *gin.Context) {
	// 获取查询参数
	studentIDStr := c.Query("student_id")
	topKStr := c.DefaultQuery("top_k", "10")

	// 参数验证
	if studentIDStr == "" {
		response.BadRequest(c, "学生ID不能为空")
		return
	}

	studentID, err := strconv.ParseUint(studentIDStr, 10, 32)
	if err != nil {
		response.BadRequest(c, "无效的学生ID")
		return
	}

	topK, err := strconv.Atoi(topKStr)
	if err != nil || topK <= 0 {
		topK = 10 // 默认返回10个推荐课题
	}
	if topK > 50 { // 限制最大值，避免性能问题
		topK = 50
	}

	// 使用ProjectService获取推荐课题
	serviceRecommendations, err := projectService.GetRecommendedProjects(uint(studentID), topK)
	if err != nil {
		logger.ErrorLog("获取推荐课题失败",
			zap.Uint64("student_id", studentID),
			zap.Int("top_k", topK),
			zap.Error(err))
		response.InternalServerError(c, "获取推荐课题失败")
		return
	}

	// 转换为handlers层的结构体
	var recommendedProjects []models.RecommendedProject
	for _, serviceRec := range serviceRecommendations {
		recommendedProjects = append(recommendedProjects, models.RecommendedProject{
			Project:    serviceRec.Project,
			MatchScore: serviceRec.MatchScore,
		})
	}

	// 如果没有找到推荐课题
	if len(recommendedProjects) == 0 {
		response.Success(c, []models.RecommendedProject{})
		return
	}

	response.SuccessWithMessage(c,
		fmt.Sprintf("成功获取%d个推荐课题", len(recommendedProjects)),
		recommendedProjects)
}

// FlexibleTime 支持多种时间格式的JSON解析
type FlexibleTime struct {
	time.Time
}

func (ft *FlexibleTime) UnmarshalJSON(b []byte) error {
	s := strings.Trim(string(b), "\"")
	if s == "null" || strings.TrimSpace(s) == "" {
		ft.Time = time.Time{}
		return nil
	}
	layouts := []string{
		time.RFC3339,
		time.RFC3339Nano,
		"2006-01-02",
		"2006-01-02 15:04:05",
	}
	var lastErr error
	for _, layout := range layouts {
		if t, err := time.Parse(layout, s); err == nil {
			ft.Time = t
			return nil
		} else {
			lastErr = err
		}
	}
	return fmt.Errorf("invalid time format: %v", lastErr)
}
